﻿//===================================================================================
// SPrello - sprello.codeplex.com
// A SharePoint ui inspired by trello.com
//===================================================================================
// Copyright (c) 2011-14 Pentalogic Technology Ltd. All rights reserved.
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using Microsoft.SharePoint.Utilities;

namespace SPrello.SPrello
{
    [ToolboxItemAttribute(false)]
    public class SPrello : WebPart
    {

        public SPrello()
        {
            this.TitleField = "Title";
        }

        #region Web Part Properties

        [WebBrowsable]
        [WebDisplayName("List Name")]
        [WebDescription("The name of the list used")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string ListName { get; set; }

        [WebBrowsable]
        [WebDisplayName("View Name (optional)")]
        [WebDescription("The name of the view to use")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string ViewName { get; set; }

        [WebBrowsable]
        [WebDisplayName("Category Field")]
        [WebDescription("The field containing the category information")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string CategoryField { get; set; }

        [WebBrowsable]
        [WebDisplayName("Order Field (optional)")]
        [WebDescription("The numeric field used for ordering")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string OrderField { get; set; }

        [WebBrowsable]
        [WebDisplayName("Title Field")]
        [WebDescription("The field containing the cards title")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string TitleField { get; set; }

        [WebBrowsable]
        [WebDisplayName("Detail Field (optional)")]
        [WebDescription("The fields containing the cards detail")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public string DetailField { get; set; }

        /// <summary>
        /// Should clicking on a card open the list items display form.
        /// </summary>
        public enum CardClickDialogOperations
        {
            Nothing = 0,
            Display_Form,
            Edit_Form
        };

        [WebBrowsable]
        [WebDisplayName("On card click show")]
        [WebDescription("What should SPRello do when a user clicks on a card")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public CardClickDialogOperations OnCardClick { get; set; }

        [WebBrowsable]
        [WebDisplayName("Allow Adding")]
        [WebDescription("Allow users to create new items")]
        [Category("Configuration")]
        [Personalizable(PersonalizationScope.User)]
        public bool AllowAdding { get; set; }

        // Debugging web part properties

        [WebBrowsable]
        [WebDisplayName("Log to console")]
        [WebDescription("Log JavaScript operations to browsers console window")]
        [Category("Debugging")]
        [Personalizable(PersonalizationScope.User)]
        public bool LogToConsole { get; set; }

        #endregion

        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);

            if (String.IsNullOrEmpty(this.ListName))
            {
                writer.Write("This web part is not yet configured. Edit the web part to setup");
                return;
            }

            if (SPContext.Current == null || SPContext.Current.Site == null || SPContext.Current.Site.RootWeb == null)
            {
                writer.Write("Error : Couldn't find SPContext.Current.Site.RootWeb");
            }

            // The path to the web parts assets directory (Layouts can't be used with Sandbox solutions) in THIS site collection
            string assetsPath = SPUrlUtility.CombineUrl(SPContext.Current.Site.RootWeb.Url, "/SiteAssets/SPrelloAssets");

            // TODO CSS - best way to do in sandbox?
            writer.Write("<link rel='stylesheet' type='text/css' href='{0}/WebPart.css?v={1}' />", assetsPath, AssemblyInfo.AssemblyFileVersion);

            // Can't use ClientScriptManager is sandbox solutions - http://msdn.microsoft.com/en-us/library/gg615454.aspx
            // Change to SP.SOB? http://blog.mastykarz.nl/dynamically-loading-javascript-sandbox/
            writer.Write("<script type='text/javascript' src='{0}/jquery.js'></script>", assetsPath);
            writer.Write("<script type='text/javascript' src='{0}/jquery-ui.js'></script>", assetsPath);

            const string javaScriptRef = "<script language='javascript' type='text/javascript' src='{0}/{1}?v={2}'></script>";
            writer.Write(javaScriptRef, assetsPath, "WebPart.js", AssemblyInfo.AssemblyFileVersion);

            #region Inline script to give configuration

            writer.Write("<script>");

            // Note escaping javascript {} with {{}} when using string formatting
            writer.Write("function sprello_setup_{0}(){{", this.ID);
            writer.Write("var sp = new SPrello(\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\", {8}, {9});",
                this.ID,
                this.ListName, this.ViewName,
                this.CategoryField, this.OrderField,
                this.TitleField, this.DetailField,
                this.OnCardClick.ToString(),
                this.AllowAdding.ToString().ToLowerInvariant(),
                this.LogToConsole.ToString().ToLowerInvariant());
            writer.Write("}\r\n");
            
            // Need to wait until sp.js library loaded (for JSOM) and also core.js (for SP.UI.Notify in 2013, on 2010 its also in sp.js)
            //http://sharepoint.stackexchange.com/questions/60866/adding-notification-from-server-side-code-ignoring-executeordelayuntilscriptloa
            writer.Write("ExecuteOrDelayUntilScriptLoaded(function(){ExecuteOrDelayUntilScriptLoaded(sprello_setup_" + this.ID + ",'sp.js');},'core.js');");

            writer.Write("</script>");

            #endregion

            renderToolbar(writer);

            writer.Write("<div id='board' class='sprello-board-container'></div>");
        }

        private void renderToolbar(HtmlTextWriter writer)
        {
            if (this.AllowAdding)
            {
                writer.Write("<div id='sprello-toolbar' class='sprello-toolbar'>");
                writer.Write("<a href='#' onclick=\"" +
                             "var sprello = $('#board').data('SPrello');if (sprello != null) sprello.AddNewCard(); " +
                             "\"><img src='_layouts/images/rect.gif' border='0'> Add new item</a>");
                writer.Write("</div>");
            }
        }

        #region IWebEditable Members

        public override EditorPartCollection CreateEditorParts()
        {
            List<EditorPart> editors = new List<EditorPart>();

            AboutToolPart configToolPart = new AboutToolPart();
            configToolPart.ID = this.ID + "_configToolPart";
            editors.Add(configToolPart);

            return new EditorPartCollection(editors);
        }

        #endregion

    }
}
